package com.cirnoworks.uhs;

import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;

import javax.inject.Singleton;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cirnoworks.common.LifeCycledThread;

@Singleton
public class LinkContainer extends LifeCycledThread {

	private final static Logger LOG = LoggerFactory
			.getLogger(LinkContainer.class);

	protected final Selector selector;

	public LinkContainer() {
		try {
			selector = Selector.open();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	protected void initLinks(Selector selector) {

	}

	protected void closeLinks(Selector selector) {

	}

	protected void beforeSelect() {

	}

	protected void afterSelect() {

	}

	@Override
	public void run() {
		// ByteBuffer buf = ByteBuffer.allocateDirect(65536);
		initLinks(selector);
		try {
			while (!isInterrupted()) {
				beforeSelect();
				try {
					if (selector.select(10000) > 0) {
						Iterator<SelectionKey> keys = selector.selectedKeys()
								.iterator();
						while (keys.hasNext()) {
							SelectionKey key = keys.next();
							Link link = (Link) key.attachment();
							if (key.isReadable()) {
								link.onDataReceived(selector);
							}
							if (key.isWritable()) {
								link.onWritable(selector);
							}
							keys.remove();
						}
					}
				} catch (IOException e) {
					LOG.error("Error ", e);
				}
				afterSelect();
			}
		} finally {
			try {
				closeLinks(selector);
			} catch (Exception e) {
				LOG.error("Error closing links", e);
			}
		}
	}

}
